// Copyright (c) 2023 The Jaeger Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package testutils

import (
	"testing"

	"go.uber.org/goleak"
)

// IgnoreGlogFlushDaemonLeak returns a goleak.Option that ignores the flushDaemon function
// from the glog package that can cause false positives in leak detection.
// This is necessary because glog starts a goroutine in the background that may not
// be stopped when the test finishes, leading to a detected but expected leak.
func IgnoreGlogFlushDaemonLeak() goleak.Option {
	return goleak.IgnoreTopFunction("github.com/golang/glog.(*fileSink).flushDaemon")
}

// IgnoreOpenCensusWorkerLeak This prevent catching the leak generated by opencensus defaultWorker.Start which at the time is part of the package's init call.
// See https://github.com/jaegertracing/jaeger/pull/5055#discussion_r1438702168 for more context.
func IgnoreOpenCensusWorkerLeak() goleak.Option {
	return goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start")
}

// VerifyGoLeaks verifies that unit tests do not leak any goroutines.
// It should be called in TestMain.
func VerifyGoLeaks(m *testing.M) {
	goleak.VerifyTestMain(m, IgnoreGlogFlushDaemonLeak(), IgnoreOpenCensusWorkerLeak())
}

// VerifyGoLeaksOnce verifies that a given unit test does not leak any goroutines.
// Occasionally useful to troubleshoot specific tests that are flaky due to leaks,
// since VerifyGoLeaks cannot distiguish which specific test caused the leak.
// It should be called via defer or from Cleanup:
//
//	defer testutils.VerifyGoLeaksOnce(t)
func VerifyGoLeaksOnce(t *testing.T) {
	goleak.VerifyNone(t, IgnoreGlogFlushDaemonLeak(), IgnoreOpenCensusWorkerLeak())
}
